package org.linlinjava.litemall.wx.web;

import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.config.DesNoViUtil;
import org.linlinjava.litemall.core.notify.NotifyService;
import org.linlinjava.litemall.core.notify.NotifyType;
import org.linlinjava.litemall.core.systemConfig.GetRegionService;
import org.linlinjava.litemall.core.systemConfig.SystemConfig;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.util.bcrypt.BCryptPasswordEncoder;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.OrderHandleOption;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.linlinjava.litemall.wx.annotation.LoginUser;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import redis.clients.jedis.Jedis;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 订单设计
 * <p>
 * 订单状态：
 * 101 订单生成，未支付；102，下单后未支付用户取消；103，下单后未支付超时系统自动取消
 * 201 支付完成，商家未发货；202，订单生产，已付款未发货，但是退款取消；
 * 301 商家发货，用户未确认；
 * 401 用户确认收货，订单结束； 402 用户没有确认收货，但是快递反馈已收获后，超过一定时间，系统自动确认收货，订单结束。
 * <p>
 * 当101用户未付款时，此时用户可以进行的操作是取消订单，或者付款操作
 * 当201支付完成而商家未发货时，此时用户可以取消订单并申请退款
 * 当301商家已发货时，此时用户可以有确认收货的操作
 * 当401用户确认收货以后，此时用户可以进行的操作是删除订单，评价商品，或者再次购买
 * 当402系统自动确认收货以后，此时用户可以删除订单，评价商品，或者再次购买
 * <p>
 * 目前不支持订单退货和售后服务
 *
 * @author All
 */
@RestController
@RequestMapping("/wx/order")
public class WxOrderController extends GetRegionService {
	private final Log logger = LogFactory.getLog(WxOrderController.class);

	private PlatformTransactionManager txManager;

	private LitemallUserService userService;

	private LitemallOrderService orderService;

	private LitemallOrderGoodsService orderGoodsService;

	private LitemallAddressService addressService;

	private LitemallProductService productService;

	private LitemallCategoryService litemallCategoryService;

	private LitemallGoodsService goodsService;

	private LitemallMechanismUserService litemallMechanismUserService;

	private LitemallWalletRecordService walletRecordService;

	private LitemallMechanismService litemallMechanismService;

	private WxPayService wxPayService;

	private NotifyService notifyService;

	/**
	 * 2级代理
	 */
	private static String LEVEL_TWO = "2";

	/**
	 * 3,4级代理编号
	 */
	private static ArrayList<String> ARRAY_LEVL3_LEVEL4 = new ArrayList<String>() {{
		add("3");
		add("4");
	}};

	public WxOrderController(
		PlatformTransactionManager txManager,
		LitemallUserService userService,
		LitemallOrderService orderService,
		LitemallOrderGoodsService orderGoodsService,
		LitemallAddressService addressService,
		LitemallProductService productService,
		LitemallCategoryService litemallCategoryService,
		LitemallGoodsService goodsService,
		LitemallMechanismUserService litemallMechanismUserService,
		LitemallWalletRecordService walletRecordService,
		WxPayService wxPayService,
		NotifyService notifyService,
		LitemallMechanismService litemallMechanismService) {
		this.txManager = txManager;
		this.userService = userService;
		this.orderService = orderService;
		this.orderGoodsService = orderGoodsService;
		this.addressService = addressService;
		this.productService = productService;
		this.litemallCategoryService = litemallCategoryService;
		this.goodsService = goodsService;
		this.litemallMechanismUserService = litemallMechanismUserService;
		this.walletRecordService = walletRecordService;
		this.wxPayService = wxPayService;
		this.notifyService = notifyService;
		this.litemallMechanismService = litemallMechanismService;
	}



	/**
	 * 订单列表
	 *
	 * @param userId   用户ID
	 * @param showType 订单信息
	 *                 0， 全部订单
	 *                 1，待付款
	 *                 2，待发货
	 *                 3，待收货
	 *                 4，待评价
	 * @return 订单操作结果
	 * 成功则
	 * {
	 * errno: 0,
	 * errmsg: '成功',
	 * data:
	 * {
	 * data: xxx ,
	 * count: xxx
	 * }
	 * }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@RequestMapping("list")
	public Object list(
		@LoginUser Integer userId, Integer showType) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		if (showType == null) {
			showType = 0;
		}

		List<Short> orderStatus = OrderUtil.orderStatus(showType);
		boolean mtype = false;
		List<LitemallOrder> orderList = orderService.queryByOrderStatus(userId, orderStatus, mtype);

		List<Map<String, Object>> orderVoList = new LinkedList<>();
		for (LitemallOrder order : orderList) {
			Map<String, Object> orderVo = new HashMap<>(16);
			orderVo.put("id", order.getId());
			orderVo.put("orderSn", order.getOrderSn());
			orderVo.put("actualPrice", order.getActualPrice());
			orderVo.put("actualIntegral", order.getActualIntegral());

			orderVo.put("orderStatusText", OrderUtil.orderStatusText(order));
			orderVo.put("handleOption", OrderUtil.build(order));

			List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
			List<Map<String, Object>> orderGoodsVoList = new LinkedList<>();
			for (LitemallOrderGoods orderGoods : orderGoodsList) {
				Map<String, Object> orderGoodsVo = new HashMap<>(16);
				orderGoodsVo.put("id", orderGoods.getId());
				orderGoodsVo.put("goodsName", orderGoods.getGoodsName());
				orderGoodsVo.put("number", orderGoods.getNumber());
				orderGoodsVo.put("picUrl", orderGoods.getPicUrl());
				orderGoodsVoList.add(orderGoodsVo);
			}
			orderVo.put("goodsList", orderGoodsVoList);

			orderVoList.add(orderVo);
		}
		Map<String, Object> result = new HashMap<>(16);

		result.put("data", orderVoList);

		return ResponseUtil.ok(result);
	}

	/**
	 * 订单详情
	 *
	 * @param userId  用户ID
	 * @param orderId 订单信息
	 * @return 订单操作结果
	 * 成功则
	 * {
	 * errno: 0,
	 * errmsg: '成功',
	 * data:
	 * {
	 * orderInfo: xxx ,
	 * orderGoods: xxx
	 * }
	 * }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@GetMapping("detail")
	public Object detail(@LoginUser Integer userId, Integer orderId) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		if (orderId == null) {
			return ResponseUtil.badArgument();
		}

		// 订单信息
		LitemallOrder order = orderService.findById(orderId);
		if (null == order) {
			return ResponseUtil.fail(403, "订单不存在");
		}
		if (!order.getUserId().equals(userId)) {
			return ResponseUtil.fail(403, "不是当前用户的订单");
		}
		Map<String, Object> orderVo = new HashMap<>(16);
		orderVo.put("id", order.getId());
		orderVo.put("orderSn", order.getOrderSn());
		orderVo.put("addTime", order.getAddTime());
		orderVo.put("consignee", order.getConsignee());
		orderVo.put("mobile", order.getMobile());
		orderVo.put("address", order.getAddress());
		orderVo.put("goodsPrice", order.getGoodsPrice());
		orderVo.put("freightPrice", order.getFreightPrice());
		orderVo.put("actualPrice", order.getActualPrice());
		orderVo.put("actualIntegral", order.getActualIntegral());

		orderVo.put("orderStatusText", OrderUtil.orderStatusText(order));
		orderVo.put("handleOption", OrderUtil.build(order));
		orderVo.put("expCode", order.getShipChannel());
		orderVo.put("expNo", order.getShipSn());

		List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
		List<Map<String, Object>> orderGoodsVoList = new ArrayList<>(orderGoodsList.size());
		boolean first = true;
		boolean second = false;
		for (LitemallOrderGoods orderGoods : orderGoodsList) {
			Map<String, Object> orderGoodsVo = new HashMap<>(16);
			orderGoodsVo.put("id", orderGoods.getId());
			orderGoodsVo.put("orderId", orderGoods.getOrderId());
			orderGoodsVo.put("goodsId", orderGoods.getGoodsId());
			orderGoodsVo.put("goodsName", orderGoods.getGoodsName());
			orderGoodsVo.put("number", orderGoods.getNumber());
			orderGoodsVo.put("retailPrice", orderGoods.getPrice());
			orderGoodsVo.put("retailIntegral", orderGoods.getIntegral());

			int orderStatus = orderService.findById(orderId).getOrderStatus();
			System.out.println(orderStatus);
			boolean flag = orderStatus != 0 && (orderStatus == 401 || orderStatus == 402 || orderStatus == 501);
			if (flag) {
				//只有在收货之后,才可以评价；用户评价一次之后可以评价订单里面的其他商品501
				orderGoodsVo.put("commentsStatus", first);
				orderGoodsVo.put("commentsStatused", second);
			} else {

				orderGoodsVo.put("commentsStatus", second);
				orderGoodsVo.put("commentsStatused", second);
			}
			boolean flag2 = orderGoods.getCommentsStatus() != null && orderGoods.getCommentsStatus() != 0;
			if (flag2) {
				int commentsStatus = orderGoods.getCommentsStatus();

				if (commentsStatus == 501) {
					orderGoodsVo.put("orderGoodsCommentsStatus", "已评价");
					orderGoodsVo.put("commentsStatused", first);
					orderGoodsVo.put("commentsStatus", second);

				} else if (commentsStatus == 502) {
					orderGoodsVo.put("orderGoodsCommentsStatus", "已追评");

					orderGoodsVo.put("commentsStatus", second);
					orderGoodsVo.put("commentsStatused", second);
				} else {
					orderGoodsVo.put("orderGoodsCommentsStatus", "");
					orderGoodsVo.put("commentsStatus", first);
					orderGoodsVo.put("commentsStatused", second);

				}
			}

			orderGoodsVo.put("integralFlag", orderGoods.getIntegralFlag());
			orderGoodsVo.put("priceFlag", orderGoods.getPriceFlag());

			orderGoodsVo.put("picUrl", orderGoods.getPicUrl());
			orderGoodsVo.put("goodsSpecificationValues", orderGoods.getSpecifications());
			orderGoodsVoList.add(orderGoodsVo);
		}

		Map<String, Object> result = new HashMap<>();
		result.put("orderInfo", orderVo);
		result.put("orderGoods", orderGoodsVoList);
		return ResponseUtil.ok(result);

	}

	/**
	 * 提交订单
	 * 1. 根据购物车ID、地址ID、优惠券ID、邮费，创建订单表项
	 * 2. 购物车清空
	 * 3. TODO 优惠券设置已用
	 * 4. 商品货品数量减少
	 *
	 * @param userId 用户ID
	 * @param body   订单信息，{ cartId：xxx, addressId: xxx, couponId: xxx, freightPrice: xxx }
	 * @return 订单操作结果
	 * 成功则 { errno: 0, errmsg: '成功', data: { orderId: xxx } }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@PostMapping("submit")
	public Object submit(@LoginUser Integer userId, @RequestBody String body) throws Exception {

		//解密
		DesNoViUtil tools = new DesNoViUtil();

		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		if (body == null) {
			return ResponseUtil.badArgument();
		}
		//1秒内用户不能重复下单
		try (Jedis jedis = new Jedis("localhost", 6379)) {
			long c = jedis.incr(userId+"order");
			if (c > 1) {
				return ResponseUtil.fail(403, "下单过于频繁，稍后再试");
			}else{
				if(c==1){
					//设置过期时间
					jedis.expire(userId+"order",1);
				}
			}
		}
		String addressIdStr = tools.decode(JacksonUtil.parseString(body, "addressId"));
		if (addressIdStr == null) {
			return ResponseUtil.fail(403, "请选择收货地址");
		}
		String mtypeStr = tools.decode(JacksonUtil.parseString(body, "mtype"));
		// 机构标志 true 为机构，false则不是
		boolean mType;
		if ("false".equals(mtypeStr)) {
			mType = false;
		} else {
			mType = true;
		}
		Integer addressId = Integer.parseInt(addressIdStr);

		String freightPriceStr = tools.decode(JacksonUtil.parseString(body, "freightPrice"));
		int freightPriceTemp = 0;
		if (!"".equals(freightPriceStr) && freightPriceStr != null) {
			freightPriceTemp = Integer.parseInt(freightPriceStr);
		}

		LitemallUser litemallUser = userService.findById(userId);

		String payPassword = tools.decode(JacksonUtil.parseString(body, "payPassword"));

		BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
		if (payPassword != null && !encoder.matches(payPassword, litemallUser.getPayPassword())) {
			return ResponseUtil.fail(403, "支付密码不对");
		}

		// 使用优惠券减免的金额
		BigDecimal couponPrice = new BigDecimal(0.00);

		//商品list

		String checkedGoodsStr = tools.decode(JacksonUtil.parseString(body, "checkedGoodsList"));

		List<String> checkedGoodsList = java.util.Arrays.asList(checkedGoodsStr.substring(1, checkedGoodsStr.length() - 1).split("},"));

		if (checkedGoodsList.size() == 0) {
			return ResponseUtil.badArgumentValue();
		}

		BigDecimal checkedGoodsPrice = new BigDecimal(0.00);
		Integer actualIntegral = 0;
		BigDecimal allReturnPrice = new BigDecimal(0.00);
		BigDecimal giveGoodsPrice = new BigDecimal(0.00);
		int giveIntegral = 0;

		List<LitemallCategory> categoryList = litemallCategoryService.getL2ByMemberNum(SystemConfig.getMemberNumber());
		List<Integer> memberGoodsNum = categoryList.stream().map(LitemallCategory::getId).collect(Collectors.toList());

		//计算积分和爱币的数量
		BigDecimal giveToMechanismNum = new BigDecimal(0.00);
		BigDecimal giveToUserNum = new BigDecimal(0.00);
		for (int i = 0; i < checkedGoodsList.size(); i++) {
			String checkedGoods = checkedGoodsList.get(i) + "}";
			String integralFlag = JacksonUtil.parseString(checkedGoods, "integralFlag");
			String priceFlag = JacksonUtil.parseString(checkedGoods, "priceFlag");
			Integer integral = JacksonUtil.parseInteger(checkedGoods, "integral");
			Integer retailPrice = JacksonUtil.parseInteger(checkedGoods, "retailPrice");
			BigDecimal price = new BigDecimal(retailPrice.toString());
			Integer number = JacksonUtil.parseInteger(checkedGoods, "number");
			Integer categoryId = JacksonUtil.parseInteger(checkedGoods, "categoryId");

			//过滤会员的商品，将商品价格存到一起，一起结算
			if (memberGoodsNum.contains(categoryId)) {
				allReturnPrice = allReturnPrice.add(price.multiply(new BigDecimal((number))));
			}

			if ("1".equals(integralFlag)) {
				actualIntegral += integral * number;
			} else {
				giveIntegral += integral * number;
			}
			if ("1".equals(priceFlag)) {
				checkedGoodsPrice = checkedGoodsPrice.add(price.multiply(new BigDecimal(number)));
			} else {
				giveGoodsPrice = giveGoodsPrice.add(price.multiply(new BigDecimal(number)));
			}
		}
		//如果是会员计算，并且绑定的机构等级大于1 计算返回的差价
		if (litemallUser.getMemberType() != null && litemallUser.getMemberType() && litemallUser.getFirstMechanism() != null) {
			String merchanismId = litemallUser.getFirstMechanism().toString();
			LitemallMechanism litemallMechanism = litemallMechanismService.findById(Integer.parseInt(merchanismId));
			if (litemallMechanism.getLevel() == null || litemallMechanism.getLevel() > (byte)1) {
				giveToMechanismNum = allReturnPrice.multiply(new BigDecimal(SystemConfig.getReturnToMechanimPercent()));
				giveToUserNum = allReturnPrice.multiply(new BigDecimal(SystemConfig.getReturnToUserPercent()));
				giveToMechanismNum = giveToMechanismNum.setScale(2, RoundingMode.HALF_UP);
				giveToUserNum = giveToUserNum.setScale(2, RoundingMode.HALF_UP);
			}
		}
		giveGoodsPrice = giveGoodsPrice.add(giveToUserNum);

		// 根据订单商品总价计算运费，满88则免运费，否则8元；
		BigDecimal freightPrice = new BigDecimal(freightPriceTemp);

		// 可以使用的其他钱，例如用户积分
		BigDecimal integralPrice = new BigDecimal(0.00);

		// 订单费用
		BigDecimal orderTotalPrice = checkedGoodsPrice.add(freightPrice).subtract(couponPrice);
		BigDecimal actualPrice = orderTotalPrice.subtract(integralPrice);
        if(actualIntegral < 600 && checkedGoodsPrice.compareTo(new BigDecimal(88)) == -1 && freightPrice.compareTo(new BigDecimal(1)) == -1){
	        return ResponseUtil.fail(403, "运费计算失败，请重新下单");
        }
		//扣除爱币和积分
		Integer userIntegral = litemallUser.getIntegral();
		BigDecimal userBalance = litemallUser.getBalance();

		if (userBalance.compareTo(actualPrice) < 0) {
			return ResponseUtil.fail(403, "您的爱币不够");
		}
		if (userIntegral < actualIntegral) {
			return ResponseUtil.fail(403, "您的积分不够");
		}
		//创建订单成功后的订单id
		Integer orderId;

		Map<String, Object> data = new HashMap<>(16);

		// 收货地址
		LitemallAddress checkedAddress = addressService.findById(addressId);

		// 开启事务管理
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		TransactionStatus status = txManager.getTransaction(def);
		LitemallOrder order;
		try {
			for (int i = 0; i < checkedGoodsList.size(); i++) {
				String checkedGoods = checkedGoodsList.get(i) + "}";
				String productName = JacksonUtil.parseString(checkedGoods, "goodsName");
				if (productName != null && productName.length() > 4) {
					productName = productName.substring(0, 4) + "..";
				}
				Integer productId = JacksonUtil.parseInteger(checkedGoods, "productId");
				Integer number = JacksonUtil.parseInteger(checkedGoods, "number");
				LitemallProduct product = productService.findById(productId);

				if (product == null) {
					txManager.rollback(status);
					return ResponseUtil.fail(403, productName + "已下架，请返回购物车中删除此商品后再下单！");
				}

				int remainNumber = product.getNumber() - number;
				if (product.getNumber() <= 0) {
					txManager.rollback(status);
					return ResponseUtil.fail(403, productName + "没有库存");
				}
				if (remainNumber < 0) {
					//库存数量不足，提示货品库存数量
					txManager.rollback(status);
					return ResponseUtil.fail(403, productName + "库存不足");
				}
				product.setNumber(remainNumber);
				productService.updateById(product);
			}

			// 生成订单
			order = new LitemallOrder();
			order.setUserId(userId);
			order.setOrderSn(orderService.generateOrderSn(userId));
			order.setAddTime(LocalDateTime.now());
			order.setOrderStatus(OrderUtil.STATUS_CREATE);
			order.setConsignee(checkedAddress.getName());
			order.setMobile(checkedAddress.getMobile());
			String detailedAddress = getdetailedAddress(checkedAddress);
			order.setAddress(detailedAddress);
			order.setGoodsPrice(checkedGoodsPrice);
			order.setGoodsIntegral(actualIntegral);
			order.setGiveIntegral(giveIntegral);
			order.setGivePrice(giveGoodsPrice);
			order.setFreightPrice(freightPrice);
			order.setCouponPrice(couponPrice);
			order.setGiveBalance(giveToMechanismNum);
			order.setActualIntegral(actualIntegral);
			//TODO 修改订单信息 价格等
			order.setOrderPrice(orderTotalPrice);
			order.setActualPrice(actualPrice);
			order.setMechanismType(mType);
			//TODO 添加订单表项
			orderService.add(order);
			orderId = order.getId();

			//TODO 添加订单商品详情
			for (int i = 0; i < checkedGoodsList.size(); i++) {
				String checkedGoods = checkedGoodsList.get(i) + "}";
				Integer goodsId = JacksonUtil.parseInteger(checkedGoods, "id");
				LitemallGoods goods = goodsService.findById(goodsId);
				String name = JacksonUtil.parseString(checkedGoods, "name");
				if (goods == null) {
					txManager.rollback(status);
					return ResponseUtil.fail(403, name + "已下架，请返回购物车中删除此商品后再下单！");
				}
				String goodsSn = JacksonUtil.parseString(checkedGoods, "goodsSn");
				Integer productId = JacksonUtil.parseInteger(checkedGoods, "productId");
				String picUrl = JacksonUtil.parseString(checkedGoods, "picUrl");
				String retailPrice = JacksonUtil.parseString(checkedGoods, "retailPrice");
				Short number = JacksonUtil.parseShort(checkedGoods, "number");
				Integer integral = JacksonUtil.parseInteger(checkedGoods, "integral");
				String specification = JacksonUtil.parseString(checkedGoods, "specifications");

				String[] specifications = specification.split(" ");

				BigDecimal price = new BigDecimal(retailPrice);

				LitemallOrderGoods orderGoods = new LitemallOrderGoods();
				orderGoods.setOrderId(order.getId());
				orderGoods.setGoodsId(goodsId);
				orderGoods.setGoodsSn(goodsSn);
				orderGoods.setProductId(productId);
				orderGoods.setGoodsName(name);
				orderGoods.setPicUrl(picUrl);
				orderGoods.setPrice(price);
				orderGoods.setNumber(number);
				orderGoods.setIntegral(integral);
				orderGoods.setPriceFlag(JacksonUtil.parseByte(checkedGoods, "priceFlag"));
				orderGoods.setIntegralFlag(JacksonUtil.parseByte(checkedGoods, "integralFlag"));
				orderGoods.setSpecifications(specifications);
				orderGoods.setAddTime(LocalDateTime.now());
				orderGoodsService.add(orderGoods);
			}

			if ((userIntegral >= order.getActualIntegral()) && (userBalance.compareTo(order.getActualPrice()) >= 0)) {
				userIntegral -= order.getActualIntegral();
				litemallUser.setIntegral(userIntegral);
				userBalance = userBalance.subtract(order.getActualPrice());
				litemallUser.setBalance(userBalance);
				order.setOrderStatus(OrderUtil.STATUS_PAY);

				//添加钱包的记录
				LitemallWalletRecord walletRecord = new LitemallWalletRecord();
				walletRecord.setUserId(userId);
				walletRecord.setType(new Byte("2"));
				walletRecord.setModifyAmount(order.getActualPrice().multiply(new BigDecimal(-1)));
				walletRecord.setModifyIntegral(order.getActualIntegral() * (-1));
				walletRecord.setPayId(order.getOrderSn());
				walletRecord.setPayTime(LocalDateTime.now());
				walletRecord.setModifyTime(LocalDateTime.now());
				walletRecord.setModifyReason("消费");
				walletRecord.setPayType(new Byte("3"));
				walletRecord.setRecordSn(createRecordSn());
				walletRecordService.add(walletRecord);
				order.setPayId(walletRecord.getRecordSn());
				order.setPayTime(walletRecord.getPayTime());
				orderService.update(order);
				userService.update(litemallUser);
			} else {
				order.setOrderStatus(OrderUtil.STATUS_CREATE);
				orderService.update(order);
			}
		}
		catch (Exception ex) {
			txManager.rollback(status);
			logger.error("系统内部错误", ex);
			return ResponseUtil.fail(403, "下单失败");
		}
		txManager.commit(status);
		//创建订单成功后的订单状态
		data.put("orderStatus", order.getOrderStatus());
		data.put("orderId", orderId);
		return ResponseUtil.ok(data);
	}

	/**
	 * 取消订单
	 * 1. 检测当前订单是否能够取消
	 * 2. 设置订单取消状态
	 * 3. 商品货品数量增加
	 *
	 * @param userId 用户ID
	 * @param body   订单信息，{ orderId：xxx }
	 * @return 订单操作结果
	 * 成功则 { errno: 0, errmsg: '成功' }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@PostMapping("cancel")
	public Object cancel(@LoginUser Integer userId, @RequestBody String body) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		if (orderId == null) {
			return ResponseUtil.badArgument();
		}

		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgumentValue();
		}
		if (!order.getUserId().equals(userId)) {
			return ResponseUtil.badArgumentValue();
		}

		// 检测是否能够取消
		OrderHandleOption handleOption = OrderUtil.build(order);
		if (!handleOption.isCancel()) {
			return ResponseUtil.fail(403, "订单不能取消");
		}

		// 开启事务管理
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		TransactionStatus status = txManager.getTransaction(def);
		try {
			// 设置订单已取消状态
			order.setOrderStatus(OrderUtil.STATUS_CANCEL);
			order.setEndTime(LocalDateTime.now());
			orderService.update(order);

			// 商品货品数量增加
			List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
			for (LitemallOrderGoods orderGoods : orderGoodsList) {
				Integer productId = orderGoods.getProductId();
				LitemallProduct product = productService.findById(productId);
				Integer number = product.getNumber() + orderGoods.getNumber();
				product.setNumber(number);
				productService.updateById(product);
			}
		}
		catch (Exception ex) {
			txManager.rollback(status);
			logger.error("系统内部错误", ex);
			return ResponseUtil.fail(403, "订单取消失败");
		}
		txManager.commit(status);
		return ResponseUtil.ok();
	}

	/**
	 * 付款订单的预支付会话标识
	 * <p>
	 * 1. 检测当前订单是否能够付款
	 * 2. 微信支付平台返回支付订单ID
	 * 3. 设置订单付款状态
	 *
	 * @param userId 用户ID
	 * @param body   订单信息，{ orderId：xxx }
	 * @return 订单操作结果
	 * 成功则 { errno: 0, errmsg: '模拟付款支付成功' }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@PostMapping("prepay")
	public Object prepay(@LoginUser Integer userId, @RequestBody String body, HttpServletRequest request) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		if (orderId == null) {
			return ResponseUtil.badArgument();
		}

		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgumentValue();
		}
		if (!order.getUserId().equals(userId)) {
			return ResponseUtil.badArgumentValue();
		}

		// 检测是否能够取消
		OrderHandleOption handleOption = OrderUtil.build(order);
		if (!handleOption.isPay()) {
			return ResponseUtil.fail(403, "订单不能支付");
		}

		LitemallUser user = userService.findById(userId);

		//扣除爱币和积分
		Integer userIntegral = user.getIntegral();
		BigDecimal userBalance = user.getBalance();

		Map<String, Object> data = new HashMap<>();

		if ((userIntegral >= order.getActualIntegral()) && (userBalance.compareTo(order.getActualPrice()) >= 0)) {
			userIntegral -= order.getActualIntegral();
			user.setIntegral(userIntegral);
			userBalance = userBalance.subtract(order.getActualPrice());
			user.setBalance(userBalance);
			userService.update(user);
			//添加钱包的记录
			LitemallWalletRecord walletRecord = new LitemallWalletRecord();
			walletRecord.setUserId(userId);
			walletRecord.setType(new Byte("2"));
			walletRecord.setModifyAmount(order.getActualPrice().multiply(new BigDecimal(-1)));
			walletRecord.setModifyIntegral(order.getActualIntegral() * (-1));
			walletRecord.setPayId(order.getOrderSn());
			walletRecord.setPayTime(LocalDateTime.now());
			walletRecord.setModifyTime(LocalDateTime.now());
			walletRecord.setModifyReason("消费");
			walletRecord.setPayType(new Byte("3"));
			walletRecord.setRecordSn(createRecordSn());
			walletRecordService.add(walletRecord);
			order.setOrderStatus(OrderUtil.STATUS_PAY);
			order.setPayId(walletRecord.getRecordSn());
			order.setPayTime(walletRecord.getPayTime());
			orderService.update(order);
		} else {
			order.setOrderStatus(OrderUtil.STATUS_CREATE);
			if (userIntegral < order.getActualIntegral()) {
				data.put("errMsg", "积分不足");
			}
			if (userBalance.compareTo(order.getActualPrice()) < 0) {
				data.put("errMsg", "爱币不足");
			}
			orderService.update(order);
		}
		data.put("orderId", order.getId());
		data.put("orderStatus", order.getOrderStatus());
		return ResponseUtil.ok(data);
	}

	private String createRecordSn() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		Date date = new Date();
		String dateStr = sdf.format(date);
		String res = (int)Math.ceil(Math.random() * 1000) + "";
		return dateStr + res;
	}

	/**
	 * 付款成功回调接口
	 * 1. 检测当前订单是否是付款状态
	 * 2. 设置订单付款成功状态相关信息
	 * 3. 响应微信支付平台
	 *
	 * @param request
	 * @param response
	 * @return 订单操作结果
	 * 成功则 WxPayNotifyResponse.success的XML内容
	 * 失败则 WxPayNotifyResponse.fail的XML内容
	 * <p>
	 * 注意，这里pay-notify是示例地址，开发者应该设立一个隐蔽的回调地址
	 */
	@PostMapping("pay-notify")
	public Object payNotify(HttpServletRequest request, HttpServletResponse response) {
		try {
			String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
			WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlResult);

			String orderSn = result.getOutTradeNo();
			String payId = result.getTransactionId();
			// 分转化成元
			String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());

			LitemallOrder order = orderService.findBySn(orderSn);
			if (order == null) {
				throw new Exception("订单不存在 sn=" + orderSn);
			}

			// 检查这个订单是否已经处理过
			if (OrderUtil.isPayStatus(order) && order.getPayId() != null) {
				return WxPayNotifyResponse.success("处理成功!");
			}

			// 检查支付订单金额
			if (!totalFee.equals(order.getActualPrice().toString())) {
				throw new Exception(order.getOrderSn() + " : 支付金额不符合 totalFee=" + totalFee);
			}

			order.setPayId(payId);
			order.setPayTime(LocalDateTime.now());
			order.setOrderStatus(OrderUtil.STATUS_PAY);
			orderService.updateById(order);

			//TODO 发送邮件和短信通知，这里采用异步发送
			// 订单支付成功以后，会发送短信给用户，以及发送邮件给管理员
			notifyService.notifyMail("新订单通知", order.toString());
			/**
			 * 这里微信的短信平台对参数长度有限制，所以将订单号只截取后6位
			 *
			 */
			notifyService.notifySmsTemplateSync(order.getMobile(), NotifyType.PAY_SUCCEED, new String[] {orderSn.substring(8, 14)});

			return WxPayNotifyResponse.success("处理成功!");
		}
		catch (Exception e) {
			logger.error("微信回调结果异常,异常原因 " + e.getMessage());
			return WxPayNotifyResponse.fail(e.getMessage());
		}
	}

	/**
	 * 订单申请退款
	 * 1. 检测当前订单是否能够退款
	 * 2. 设置订单申请退款状态
	 *
	 * @param userId 用户ID
	 * @param body   订单信息，{ orderId：xxx }
	 * @return 订单操作结果
	 * 成功则 { errno: 0, errmsg: '成功' }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@PostMapping("refund")
	public Object refund(@LoginUser Integer userId, @RequestBody String body) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		if (orderId == null) {
			return ResponseUtil.badArgument();
		}

		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgument();
		}
		if (!order.getUserId().equals(userId)) {
			return ResponseUtil.badArgumentValue();
		}

		OrderHandleOption handleOption = OrderUtil.build(order);
		if (!handleOption.isRefund()) {
			return ResponseUtil.fail(403, "订单不能取消");
		}

		// 设置订单申请退款状态
		order.setOrderStatus(OrderUtil.STATUS_REFUND);
		orderService.update(order);

		//TODO 发送邮件和短信通知，这里采用异步发送
		// 有用户申请退款，邮件通知运营人员
		notifyService.notifyMail("退款申请", order.toString());

		return ResponseUtil.ok();
	}

	/**
	 * 确认收货
	 * 1. 检测当前订单是否能够确认订单
	 * 2. 设置订单确认状态
	 * 3. 检查订单赠送信息 并返还给用户
	 *
	 * @param userId 用户ID
	 * @param body   订单信息，{ orderId：xxx }
	 * @return 订单操作结果
	 * 成功则 { errno: 0, errmsg: '成功' }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@PostMapping("confirm")
	public Object confirm(@LoginUser Integer userId, @RequestBody String body) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		if (orderId == null) {
			return ResponseUtil.badArgument();
		}

		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgument();
		}
		if (!order.getUserId().equals(userId)) {
			return ResponseUtil.badArgumentValue();
		}

		OrderHandleOption handleOption = OrderUtil.build(order);
		if (!handleOption.isConfirm()) {
			return ResponseUtil.fail(403, "订单不能确认收货");
		}
		// 开启事务管理
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		TransactionStatus status = txManager.getTransaction(def);

		try {
			order.setOrderStatus(OrderUtil.STATUS_CONFIRM);
			order.setConfirmTime(LocalDateTime.now());
			orderService.update(order);

			Integer giveIntegral = order.getGiveIntegral();
			BigDecimal givePrice = order.getGivePrice();
			BigDecimal givePriceMechanism = order.getGiveBalance();

			if (giveIntegral != 0 || givePrice.compareTo(new BigDecimal(0)) != 0) {
				//存在返还的积分或者爱币
				//返还到用户钱包
				LitemallUser user = userService.findById(userId);
				user.setIntegral(user.getIntegral() + giveIntegral);
				user.setBalance(user.getBalance().add(givePrice));
				userService.update(user);
				//返还机构钱包
				if (givePriceMechanism.compareTo(new BigDecimal(0)) != 0 && givePriceMechanism != null) {
					if (user.getFirstMechanism() != null) {
						//用户所在的机构的登录人员下的账号
						LitemallMechanismUser mechanismUser = litemallMechanismUserService.queryByMechanismId(user.getFirstMechanism());
						//用户所在的机构
						LitemallMechanism litemallMechanism = litemallMechanismService.findById(user.getFirstMechanism());
						//1 如果此机构的等级为2 有代理 代理机构获取2%
						if (litemallMechanism.getLevel() != null && LEVEL_TWO.equals(litemallMechanism.getLevel().toString())) {
							//并且代理归属的等级为3或4 ，将2%的交易额返还给代理归属机构下用户的账户
							if (litemallMechanism.getAffiliation() != null) {
								LitemallMechanism litemallMechanism1 = litemallMechanismService.findValid(litemallMechanism.getAffiliation());
								if (litemallMechanism1 !=null && ARRAY_LEVL3_LEVEL4.contains(litemallMechanism1.getLevel().toString())) {
									//获取代理归属的人员账号，将金额打入这个账号，并且添加钱包记录
									LitemallMechanismUser litemallMechanismUser = litemallMechanismUserService.queryByMechanismId(litemallMechanism1.getId());
									if (litemallMechanismUser != null) {
										if (litemallMechanismUser.getBalance() == null) {
											litemallMechanismUser.setBalance(givePriceMechanism);
										} else {
											litemallMechanismUser.setBalance(litemallMechanismUser.getBalance().add(givePriceMechanism));
										}
										litemallMechanismUserService.update(litemallMechanismUser);
									}
									LitemallWalletRecord meWalletRecord1 = new LitemallWalletRecord();
									meWalletRecord1.setMechaismId(litemallMechanismUser.getId());
									meWalletRecord1.setModifyAmount(givePriceMechanism);
									meWalletRecord1.setModifyTime(LocalDateTime.now());
									meWalletRecord1.setModifyReason("子机构会员购买会员商品返利");
									meWalletRecord1.setType(new Byte("5"));
									walletRecordService.add(meWalletRecord1);
								}
							}
						}

						//2 如果此机构的等级大于2，查看是否是新代理 ，如果是，通过用户是否是新会员 如果是 ，则将2%返给本机构。不返给代理
						//                                       如果不是，则返给机构和代理
						if (litemallMechanism.getLevel() != null && ARRAY_LEVL3_LEVEL4.contains(litemallMechanism.getLevel().toString())) {
							// 是新代理 查看用户是不是新会员
							if (litemallMechanism.getNewProxyFlag()) {
								if (user.getNewProxyFlag()) {
									// 不用返给代理机构了
								} else {
									// 返给代理机构
									if (litemallMechanism.getAffiliation() != null) {
										LitemallMechanism litemallMechanism1 = litemallMechanismService.findValid(litemallMechanism.getAffiliation());
										if (litemallMechanism1 !=null && ARRAY_LEVL3_LEVEL4.contains(litemallMechanism1.getLevel().toString())) {
											//获取代理归属的人员账号，将金额打入这个账号，并且添加钱包记录
											LitemallMechanismUser litemallMechanismUser = litemallMechanismUserService.queryByMechanismId(litemallMechanism1.getId());
											if (litemallMechanismUser != null) {
												if (litemallMechanismUser.getBalance() == null) {
													litemallMechanismUser.setBalance(givePriceMechanism);
												} else {
													litemallMechanismUser.setBalance(litemallMechanismUser.getBalance().add(givePriceMechanism));
												}
												litemallMechanismUserService.update(litemallMechanismUser);
											}
											LitemallWalletRecord meWalletRecord1 = new LitemallWalletRecord();
											meWalletRecord1.setMechaismId(litemallMechanismUser.getId());
											meWalletRecord1.setModifyAmount(givePriceMechanism);
											meWalletRecord1.setModifyTime(LocalDateTime.now());
											meWalletRecord1.setModifyReason("子机构会员购买会员商品返利");
											meWalletRecord1.setType(new Byte("5"));
											walletRecordService.add(meWalletRecord1);
										}
									}
								}
							} else {
                              // 老代理（原机构等级就是3或4），是老用户 就返代理2%
								if(!user.getNewProxyFlag()){
									if (litemallMechanism.getAffiliation() != null) {
										LitemallMechanism litemallMechanism1 = litemallMechanismService.findValid(litemallMechanism.getAffiliation());
										if (litemallMechanism1 !=null && ARRAY_LEVL3_LEVEL4.contains(litemallMechanism1.getLevel().toString())) {
											//获取代理归属的人员账号，将金额打入这个账号，并且添加钱包记录
											LitemallMechanismUser litemallMechanismUser = litemallMechanismUserService.queryByMechanismId(litemallMechanism1.getId());
											if (litemallMechanismUser != null) {
												if (litemallMechanismUser.getBalance() == null) {
													litemallMechanismUser.setBalance(givePriceMechanism);
												} else {
													litemallMechanismUser.setBalance(litemallMechanismUser.getBalance().add(givePriceMechanism));
												}
												litemallMechanismUserService.update(litemallMechanismUser);
											}
											LitemallWalletRecord meWalletRecord1 = new LitemallWalletRecord();
											meWalletRecord1.setMechaismId(litemallMechanismUser.getId());
											meWalletRecord1.setModifyAmount(givePriceMechanism);
											meWalletRecord1.setModifyTime(LocalDateTime.now());
											meWalletRecord1.setModifyReason("子机构会员购买会员商品返利");
											meWalletRecord1.setType(new Byte("5"));
											walletRecordService.add(meWalletRecord1);
										}
									}
								}
							}
						}

						// 机构得到返 2%
						LitemallWalletRecord meWalletRecord = new LitemallWalletRecord();
						if (mechanismUser != null) {
							if (mechanismUser.getBalance() == null) {
								mechanismUser.setBalance(givePriceMechanism);
							} else {
								mechanismUser.setBalance(mechanismUser.getBalance().add(givePriceMechanism));
							}
							litemallMechanismUserService.update(mechanismUser);
							//添加机构的钱包记录
							meWalletRecord.setMechaismId(mechanismUser.getId());
							meWalletRecord.setModifyAmount(givePriceMechanism);
							meWalletRecord.setModifyTime(LocalDateTime.now());
							meWalletRecord.setModifyReason("会员用户购买商品");
							meWalletRecord.setType(new Byte("5"));
							walletRecordService.add(meWalletRecord);
						} else {
							//添加爱联的钱包记录
							meWalletRecord.setMechaismId(SystemConfig.getAiLianNum());
							meWalletRecord.setModifyAmount(givePriceMechanism);
							meWalletRecord.setType(new Byte("5"));
							meWalletRecord.setModifyReason("会员用户购买商品");
							meWalletRecord.setModifyTime(LocalDateTime.now());
							walletRecordService.add(meWalletRecord);

							//爱联账户加钱
							LitemallMechanismUser aiLianMechanismUser = litemallMechanismUserService.findById(SystemConfig.getAiLianNum());
							if (aiLianMechanismUser.getBalance() == null) {
								aiLianMechanismUser.setBalance(givePriceMechanism);
							} else {
								aiLianMechanismUser.setBalance(aiLianMechanismUser.getBalance().add(givePriceMechanism));
							}
							litemallMechanismUserService.update(aiLianMechanismUser);

						}
					}
				}
				//添加用户钱包的记录
				LitemallWalletRecord walletRecord = new LitemallWalletRecord();
				LocalDateTime nowTime = LocalDateTime.now();
				String recordSn = this.createRecordSn();
				walletRecord.setUserId(userId);
				walletRecord.setRecordSn(recordSn);
				walletRecord.setType(new Byte("5"));
				walletRecord.setModifyAmount(givePrice);
				walletRecord.setModifyIntegral(giveIntegral);
				walletRecord.setPayId(recordSn);
				walletRecord.setPayTime(nowTime);
				walletRecord.setModifyTime(nowTime);
				walletRecord.setModifyReason("会员用户消费返赠");
				walletRecordService.add(walletRecord);

				//添加机构钱包记录

			}
			txManager.commit(status);
		}
		catch (Exception e) {
			txManager.rollback(status);
			e.printStackTrace();
		}

		return ResponseUtil.ok();
	}

	/**
	 * 删除订单
	 * 1. 检测当前订单是否删除
	 * 2. 设置订单删除状态
	 *
	 * @param userId 用户ID
	 * @param body   订单信息，{ orderId：xxx }
	 * @return 订单操作结果
	 * 成功则 { errno: 0, errmsg: '成功' }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@PostMapping("delete")
	public Object delete(@LoginUser Integer userId, @RequestBody String body) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		if (orderId == null) {
			return ResponseUtil.badArgument();
		}

		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgument();
		}
		if (!order.getUserId().equals(userId)) {
			return ResponseUtil.badArgumentValue();
		}

		OrderHandleOption handleOption = OrderUtil.build(order);
		if (!handleOption.isDelete()) {
			return ResponseUtil.fail(403, "订单不能删除");
		}

		// 订单order_status没有字段用于标识删除
		// 而是存在专门的delete字段表示是否删除
		orderService.deleteById(orderId);

		return ResponseUtil.ok();
	}

	/**
	 * 可以评价的订单商品信息
	 *
	 * @param userId  用户ID
	 * @param orderId 订单ID
	 * @param goodsId 商品ID
	 * @return 订单操作结果
	 * 成功则 { errno: 0, errmsg: '成功', data: xxx }
	 * 失败则 { errno: XXX, errmsg: XXX }
	 */
	@GetMapping("comment")
	public Object comment(@LoginUser Integer userId, Integer orderId, Integer goodsId) {
		if (userId == null) {
			return ResponseUtil.unlogin();
		}
		if (orderId == null) {
			return ResponseUtil.badArgument();
		}

		List<LitemallOrderGoods> orderGoodsList = orderGoodsService.findByOidAndGid(orderId, goodsId);
		int size = orderGoodsList.size();

		Assert.state(size < 2, "存在多个符合条件的订单商品");

		if (size == 0) {
			return ResponseUtil.badArgumentValue();
		}

		LitemallOrderGoods orderGoods = orderGoodsList.get(0);
		return ResponseUtil.ok(orderGoods);
	}
}